﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Semantics;
namespace GraphBase.Presentation
{
    /// <summary>
    /// 查找选中节点对应跳数的节点集合，与节点位置相关
    /// </summary>
    class NodePosSearchEngine
    {
        public NodePosSearchEngine(IGraph graphbase, GraphPositionManager positionmanager)
        {
            this.GraphDatabase = graphbase;
            this.GraphPositionManager = positionmanager;
        }
        IGraph GraphDatabase;
        GraphPositionManager GraphPositionManager;
        List<NodePos> Getneighbors(Node node)
        {
            List<NodePos> Relationneighbors = new List<NodePos>();
            Relationneighbors.Clear();
            IList<Edge> neighbornodes = this.GraphDatabase.GetEdges(node);
            foreach (Edge edge in neighbornodes)
            {
                Node neighbornode = edge.GetOtherEnd(node);
                foreach (NodePos np in this.GraphPositionManager.NodePositions.Values)
                {
                    if (neighbornode.Id == np.pNode.Id)
                    {
                        Relationneighbors.Add(np);
                    }
                }
            }
            return Relationneighbors;
        }
        
        public List<SortedList<int, NodePos>> Search(int distance, NodePos origial)
        {
            List<SortedList<int, NodePos>> Neighbors = new List<SortedList<int, NodePos>>();
            SortedList<int, NodePos> prev = null;
            //初始节点的关联节点
            for (int hop = 0; hop <= distance; hop++)
            {
                SortedList<int, NodePos> current = new SortedList<int, NodePos>();
                Neighbors.Add(current);
                if (hop == 0)
                {
                    current.Add(origial.pNode.Id, origial);
                }
                else
                {
                    foreach (NodePos prevnode in prev.Values)
                    {
                        List<NodePos> neighbors = this.Getneighbors(prevnode.pNode);
                        foreach (NodePos node in neighbors)
                        {
                            if (IsVisited(hop, node, Neighbors) == false)
                                current.Add(node.pNode.Id, node);
                        }
                    }
                }

                prev = current;
            }
            return Neighbors;
        }
        //判断hop跳的nodepos节点是否被访问过
        bool IsVisited(int hop, NodePos nodepos, List<SortedList<int, NodePos>> tempsearchnodes)
        {
            //判断与hop减一层往上的所有节点是否相同
            foreach (SortedList<int, NodePos> tempnodepos in tempsearchnodes)
            {
                foreach (NodePos np in tempnodepos.Values)
                {
                    if (nodepos.pNode.Id == np.pNode.Id)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        public List<SortedList<int, NodePos>> PrepareNeighbor(List<SortedList<int, Node>> neighborNodes)
        {
            List<SortedList<int, NodePos>> neighborPos=new List<SortedList<int,NodePos>>();
            for (int dis = 0; dis < neighborNodes.Count; dis++)
            {
                SortedList<int, Node> level = neighborNodes[dis];
                SortedList<int, NodePos> levelpos = new SortedList<int, NodePos>();
                neighborPos.Add(levelpos);
                foreach (Node node in level.Values)
                {
                    NodePos pos;
                    if (!this.GraphPositionManager.NodePositions.TryGetValue(node.Id, out pos))
                        pos = this.GraphPositionManager.PrepareNode(node);
                    levelpos.Add(node.Id, pos);
                }
            }
            return neighborPos;
        }

        /// <summary>
        /// 搜索邻接节点
        /// ？？超过一定数量许要退出
        /// </summary>
        /// <param name="Neighbors"></param>
        /// <returns></returns>
        public List<SortedList<int, List<Edge>>> Edges(List<SortedList<int, NodePos>> Neighbors)
        {
            int total = 0;
            List<SortedList<int, List<Edge>>> relationEdges = new List<SortedList<int, List<Edge>>>();
            SortedList<int, NodePos>[] Neigharray = Neighbors.ToArray();
            for (int k = 1; k < Neighbors.Count; k++)
            {
                SortedList<int, List<Edge>> hopEdges = new SortedList<int, List<Edge>>();
                int i = 0;
                foreach (NodePos neighbor in Neigharray[k].Values)
                {
                    foreach (NodePos neinode in Neigharray[k - 1].Values)
                    {
                        IList<Edge> edges1 = this.GraphDatabase.GetEdges(neighbor.pNode, neinode.pNode);
                        IList<Edge> edges2 = this.GraphDatabase.GetEdges(neinode.pNode, neighbor.pNode);
                        List<Edge> edges = new List<Edge>();
                        if(edges1!=null&&edges1.Count>0)
                            edges.AddRange(edges1);
                        if (edges2 != null && edges2.Count > 0)
                            edges.AddRange(edges2);
                        if (edges.Count > 0)
                        {
                            hopEdges.Add(i++, edges);
                            total++;
                        }
                    }
                }
                relationEdges.Add(hopEdges);
            }
            return relationEdges;
        }
    }
}
